package com.qlhx.controller;

import java.nio.charset.StandardCharsets;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSON;
import com.qlhx.common.model.ApiResult;
import com.qlhx.common.model.DataGridResult;
import com.qlhx.common.util.DateUtil;
import com.qlhx.model.Key;
import com.qlhx.model.Path;
import com.qlhx.model.PathDetail;
import com.qlhx.model.PersonGroupImpl;
import com.qlhx.model.BO.PersonBO;
import com.qlhx.mq.MQSender;
import com.qlhx.service.KeyService;
import com.qlhx.service.PathDetailService;
import com.qlhx.service.PathService;
import com.qlhx.service.PersonGroupService;
import com.qlhx.util.Constant;
import com.qlhx.util.FilterEnum;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Api(value = "控制服务-微服务之间调用的接口", description = "控制服务-微服务之间调用的接口")
@CrossOrigin(maxAge = 3600)
@RestController
@Scope(value = "prototype") 
@RequestMapping("service")
public class ServiceController {
	
	private  final Logger logger = LoggerFactory.getLogger(ServiceController.class);
	
	@Autowired
	RedisTemplate<String, Object> myRedis;
	
	@Autowired
	RestTemplate restTemplate;
	
	@Autowired
    private MQSender sender;
	
	
	private final String LOG_KEY ="logKey";
	
	
	@Autowired
	PersonGroupService personGroupService;
	
	@Autowired
	KeyService keyService;
	
	@Autowired
	PathService pathService;
	
	@Autowired
	PathDetailService pathDetailService;
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "list", method = RequestMethod.POST ,produces = { "application/json" })
	public @ResponseBody DataGridResult list(Integer offset, Integer limit) {

		HttpHeaders headers = new HttpHeaders();
		MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
		headers.setContentType(type);
		HttpEntity formEntity = new HttpEntity(null, headers);
		ResponseEntity<ApiResult> res = restTemplate.postForEntity("http://service-door/entranceGuard/list", formEntity,
				ApiResult.class);
		ApiResult<List> apiResult = res.getBody();
		DataGridResult dataGridResult = new DataGridResult();
		dataGridResult.setTotal(apiResult.getContent().size());
		dataGridResult.setRows(apiResult.getContent());
		return dataGridResult;
	}
	
	@ApiOperation(value ="获得日志" ,notes ="获得日志")
	@RequestMapping(value = "/getlog",method = RequestMethod.POST, produces = {
    "application/json"}, consumes = {"application/json"})
	public @ResponseBody ApiResult<String> getlog(HttpServletRequest request
			) 
	{
		ApiResult<String> result = new ApiResult<String>();
		String sumValue = "";
		while(true)
		{
			String value = (String)myRedis.opsForList().rightPop(LOG_KEY);
			if(value != null)
			{
				sumValue += "["+DateUtil.dateToStringWithTime()+"] " + value + "||";
			}
			else
			{
				break;
			}
					
		}
		result.setContent(sumValue);
		return result;

	}
	
	@ApiOperation(value ="存入日志" ,notes ="存入日志")
	@RequestMapping(value = "/putlog",method = RequestMethod.POST)
	public @ResponseBody ApiResult<String> putlog(@RequestBody String info, HttpServletRequest request
			) 
	{
		logger.info("====收到信息:"+info);
		ApiResult<String> result = new ApiResult<String>();
		myRedis.opsForList().leftPush(LOG_KEY,info);
		
		if(myRedis.opsForList().size(LOG_KEY)> 10)
		{
			myRedis.opsForList().trim(LOG_KEY, 0, 10);
		}
		return result;

	}
	
	@ApiOperation(value ="远程开门" ,notes ="远程开门")
	@RequestMapping(value = "/openDoor/{sn}",method = RequestMethod.GET, produces = {
    "application/json"})
	public @ResponseBody ApiResult<String> openDoor(@PathVariable long sn)
	{
		ApiResult result = null;
		OpenDoorModel openDoorModel = new OpenDoorModel();
		openDoorModel.setSn(sn);
		openDoorModel.setDoorNo(1);
		try {
			 HttpHeaders headers = new HttpHeaders();
		        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
		        headers.setContentType(type);
			HttpEntity<OpenDoorModel> formEntity = new HttpEntity<OpenDoorModel>(openDoorModel, headers);
			result = restTemplate.postForObject("http://service-door/entranceGuard/openDoor", formEntity, ApiResult.class);
//			RestTemplateUitl<OpenDoorModel,ApiResult<String>> restTemplateUitl =new RestTemplateUitl<OpenDoorModel,ApiResult<String>>();
//			result = restTemplateUitl.postByJson(restTemplate, "http://service-door/entranceGuard/openDoor", openDoorModel,ApiResult.class);
		} catch (Exception e) {
			if(result == null)
			{
				result = new ApiResult<String>();
			}
			result.getErrorResult(e);
		}
		
		
		return result;
	}
	
	@ApiOperation(value ="接收卡号" ,notes ="接收卡号")
	@RequestMapping(value = "/receiveCard/{sn}/{cardNum}/{doorNo}/{inOrOut}",method = RequestMethod.GET, produces = {
    "application/json"})
	public @ResponseBody ApiResult<String> receiveCard(@PathVariable Long sn,@PathVariable String cardNum,@PathVariable Integer doorNo,@PathVariable Integer inOrOut)
	{
		ApiResult<String> result = new ApiResult<String>();
		loggerRedis("接收到:sn="+sn+" cardNum="+cardNum+" doorNo="+doorNo+" inOrOut="+inOrOut + " (1:进 2:出)");
		
		String filterValue = (String)myRedis.opsForValue().get(Constant.FILTER_KEY);
		if(filterValue == null)
		{
			filterValue = "0";
		}
		loggerRedis("filter过滤器当前设置为:"+FilterEnum.values()[Integer.parseInt(filterValue)]);
		
		if(filterValue.equals("3") && inOrOut != 1)//只能进
		{
			loggerRedis("卡号:"+cardNum+" 是出，被禁止");
			return result;
		}
		else if(filterValue.equals("4") && inOrOut != 2)//只能出
		{
			loggerRedis("卡号:"+cardNum+" 是进，被禁止");
			return result;
		}
		
		if(filterValue.equals("0"))
		{
			ApiResult<PersonBO> res = getUserByCardNum(cardNum);
			if(res.getCode() == 1000)
			{
				PersonBO personBO = res.getContent();
				String type = (personBO.getType() == 1)?"员工":"访客";
				loggerRedis("卡号:"+cardNum+" 查询到"+type+" "+personBO.getName()+" 所属组:"+personBO.getGroupname());
				PersonGroupImpl personGroupImpl = personGroupService.selectByIdentifier(personBO.getGroupidentifier());
				loggerRedis("卡号:"+cardNum+" 开始校验 人员的凭证规则");
				Key key = keyService.selectByPrimaryKey(personGroupImpl.getKeyId());
				if(key.getCard().substring(3, 4).equals("1"))
				{
					loggerRedis("卡号:"+cardNum+" 校验 人员的凭证规则 通过");
					loggerRedis("卡号:"+cardNum+" 开始校验 人员的路径规则");
					Path path = pathService.selectByPrimaryKey(personGroupImpl.getPathId());
					List<PathDetail> pathDetailList = pathDetailService.list(path.getId());
					if(pathDetailList == null || pathDetailList.size() ==0)
					{
						loggerRedis("卡号:"+cardNum+" 校验 人员的路径规则失败,没有任何路径");
					}
					else
					{
						PathDetail pathDetailTmp = null;
						for(PathDetail pathDetail: pathDetailList)
						{
							if(pathDetail.getDeviceIdentifier().equals(sn+""))
							{
								pathDetailTmp = pathDetail;
								break;
							}
						}
						
						if(pathDetailTmp == null)
						{
							loggerRedis("卡号:"+cardNum+" 校验 人员的路径规则失败,没有sn:"+sn+" 的权限"); 
						}
						else 
						{
							if(pathDetailTmp.getInOrOut() != 0 && pathDetailTmp.getInOrOut() != inOrOut)
							{
								loggerRedis("卡号:"+cardNum+" 校验 人员的路径规则失败,没有sn:"+sn+" 的"+inOrOut+" 权限"); 
							}
							else
							{
								ApiResult r = openDoor(sn,doorNo);
								loggerRedis("卡号:"+cardNum+" 校验 人员的所有规则全部通过,开门结果:" + JSON.toJSONString(r)); 
							}
						}
					}
				}
				else
				{
					loggerRedis("卡号:"+cardNum+" 校验 人员的凭证规则 不同通过，不能使用ic卡");
				}
			}
			else
			{
				loggerRedis("卡号:"+cardNum+" 查找人员失败，结果:"+JSON.toJSONString(res));
			}
			logger.info(JSON.toJSONString(res));
		}
		else if(filterValue.equals("1"))
		{
			logger.info("=====过滤器：全部闸机关闭,所有卡都不能开门=====");
		}
		else if(filterValue.equals("2"))
		{
			logger.info("=====过滤器：全部闸机常开，可以使用任意卡开门=====");
			ApiResult r = openDoor(sn,doorNo);
			logger.info("=====开门结果："+JSON.toJSONString(r)+"=====");
		}
		
		return result;
	}
	
	/**
	 * 远程开门
	 * @param sn
	 * @param doorNo
	 * @return
	 */
	private ApiResult openDoor(Long sn,Integer doorNo)
	{

		ApiResult result = null;
		OpenDoorModel openDoorModel = new OpenDoorModel();
		openDoorModel.setSn(sn);
		openDoorModel.setDoorNo(1);
		try {
			HttpHeaders headers = new HttpHeaders();
			MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
			headers.setContentType(type);
			HttpEntity<OpenDoorModel> formEntity = new HttpEntity<OpenDoorModel>(openDoorModel, headers);
			result = restTemplate.postForObject("http://service-door/entranceGuard/openDoor", formEntity,
					ApiResult.class);
		} catch (Exception e) {
			if (result == null) {
				result = new ApiResult<String>();
			}
			result.getErrorResult(e);
		}
		return result;
	}
	
	/**
	 * 根据卡号获得员工或访客
	 * @param cardNum
	 * @return
	 */
	private  ApiResult<PersonBO> getUserByCardNum(String cardNum )
	{
		restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
//		ApiResult<PersonBO> res = restTemplate.getForObject("http://service-base/service/getUserByCardNum/" + cardNum,
//				ApiResult.class);
		ApiResult<PersonBO> res = restTemplate.exchange("http://service-base/service/getUserByCardNum/" + cardNum, HttpMethod.GET, null,  new ParameterizedTypeReference<ApiResult<PersonBO>>() {}).getBody();
		return res;
	}
	
	/**
	 * 输出日志并存入redis
	 * @param logInfo
	 */
	private void loggerRedis(String logInfo)
	{
		logger.info(logInfo);
		sender.sendLog("刷卡", logInfo);
		myRedis.opsForList().leftPush(LOG_KEY,"[" + DateUtil.dateToStringWithTime() + "] " +logInfo);
		if(myRedis.opsForList().size(LOG_KEY)> 10)
		{
			myRedis.opsForList().trim(LOG_KEY, 0, 10);
		}
	}
	

}
